# -*- coding: utf-8 -*-
import frappe
from frappe.model.document import Document
from frappe.utils import flt, cint, nowdate, nowtime, get_datetime, format_datetime
from frappe.permissions import add_permission

class BatchMaterialList(Document):
    """
    批次领料清单控制器
    处理批次领料清单的数据验证和业务逻辑
    """
    
    def validate(self):
        """验证数据有效性"""
        self.validate_material_list_id()
        self.validate_warehouse()
        self.validate_materials()
        self.set_material_date()
        self.set_created_info()
    
    def validate_material_list_id(self):
        """验证领料清单编号唯一性"""
        if not self.material_list_id:
            self.material_list_id = self.generate_material_list_id()
            return
        
        # 检查编号唯一性
        if frappe.db.exists("Batch Material List", {"material_list_id": self.material_list_id, "name": ["!=", self.name]}):
            frappe.throw(f"领料清单编号 {self.material_list_id} 已存在，请使用其他编号")
    
    def generate_material_list_id(self):
        """生成领料清单编号"""
        # 格式: BML-YYYYMMDD-NNNN
        from frappe.model.naming import make_autoname
        return make_autoname("BML-.YYYYMMDD-.#####")
    
    def validate_warehouse(self):
        """验证仓库有效性"""
        if not self.warehouse:
            frappe.throw("请选择仓库")
        
        # 检查仓库是否存在
        if not frappe.db.exists("Scrap Warehouse", self.warehouse):
            frappe.throw(f"仓库 {self.warehouse} 不存在")
        
        # 检查仓库状态
        warehouse_status = frappe.db.get_value("Scrap Warehouse", self.warehouse, "status")
        if warehouse_status != "启用":
            frappe.throw(f"仓库 {self.warehouse} 状态为 {warehouse_status}，无法使用")
    
    def validate_materials(self):
        """验证余料列表"""
        if not self.materials or len(self.materials) == 0:
            frappe.throw("请添加至少一项余料")
        
        # 验证每个余料项
        for item in self.materials:
            if not item.scrap_material:
                frappe.throw("请选择余料")
            
            if not item.location:
                frappe.throw("请选择库位")
            
            if not item.quantity or flt(item.quantity) <= 0:
                frappe.throw("数量必须大于0")
            
            # 检查余料状态
            scrap_material_status = frappe.db.get_value("Scrap Material", item.scrap_material, "status")
            if scrap_material_status != "可用":
                frappe.throw(f"余料 {item.scrap_material} 状态为 {scrap_material_status}，无法添加到领料清单")
            
            # 检查余料是否在指定库位
            scrap_material_location = frappe.db.get_value("Scrap Material", item.scrap_material, "location")
            if scrap_material_location != item.location:
                frappe.throw(f"余料 {item.scrap_material} 不在库位 {item.location} 中")
            
            # 检查数量是否超过可用数量
            available_quantity = frappe.db.get_value("Scrap Material", item.scrap_material, "quantity")
            if flt(item.quantity) > flt(available_quantity):
                frappe.throw(f"余料 {item.scrap_material} 数量 {item.quantity} 超过可用数量 {available_quantity}")
    
    def set_material_date(self):
        """设置领料日期"""
        if not self.material_date:
            self.material_date = nowdate()
    
    def set_created_info(self):
        """设置创建信息"""
        if not self.created_by:
            self.created_by = frappe.session.user
            self.created_date = get_datetime()
    
    def before_submit(self):
        """提交前处理"""
        # 设置状态信息
        if self.status == "已审批":
            self.approved_by = frappe.session.user
            self.approved_date = get_datetime()
        elif self.status == "已领料":
            self.issued_by = frappe.session.user
            self.issued_date = get_datetime()
        elif self.status == "已完成":
            self.completed_by = frappe.session.user
            self.completed_date = get_datetime()
    
    def on_submit(self):
        """提交后处理"""
        # 创建事务记录
        self.create_material_transaction()
    
    def before_cancel(self):
        """取消前处理"""
        # 检查是否可以取消
        if self.status not in ["草稿", "待审批", "已审批"]:
            frappe.throw(f"状态为 {self.status} 的领料清单无法取消")
    
    def on_cancel(self):
        """取消后处理"""
        # 创建取消事务记录
        self.create_cancel_transaction()
    
    def create_material_transaction(self):
        """创建领料事务记录"""
        for item in self.materials:
            doc = frappe.new_doc("Scrap Transaction")
            doc.transaction_type = "领料"
            doc.transaction_date = self.material_date
            doc.scrap_material = item.scrap_material
            doc.warehouse = self.warehouse
            doc.location = item.location
            doc.quantity = item.quantity
            doc.reference_doctype = "Batch Material List"
            doc.reference_name = self.name
            doc.notes = f"批次领料清单 {self.material_list_id} 领料"
            doc.insert(ignore_permissions=True)
    
    def create_cancel_transaction(self):
        """创建取消事务记录"""
        for item in self.materials:
            doc = frappe.new_doc("Scrap Transaction")
            doc.transaction_type = "取消领料"
            doc.transaction_date = nowdate()
            doc.scrap_material = item.scrap_material
            doc.warehouse = self.warehouse
            doc.location = item.location
            doc.quantity = item.quantity
            doc.reference_doctype = "Batch Material List"
            doc.reference_name = self.name
            doc.notes = f"取消批次领料清单 {self.material_list_id}"
            doc.insert(ignore_permissions=True)
    
    def calculate_total_quantity(self):
        """计算总数量"""
        total_quantity = 0
        for item in self.materials:
            total_quantity += flt(item.quantity)
        self.total_quantity = total_quantity
    
    def calculate_total_amount(self):
        """计算总金额"""
        total_amount = 0
        for item in self.materials:
            total_amount += flt(item.amount)
        self.total_amount = total_amount
    
    def submit_for_approval(self):
        """提交审批"""
        if self.status != "草稿":
            frappe.throw("只有草稿状态的清单才能提交审批")
        
        self.status = "待审批"
        self.save()
        
        # 发送通知
        self.send_approval_notification()
        
        return True
    
    def approve(self):
        """审批"""
        if self.status != "待审批":
            frappe.throw("只有待审批状态的清单才能审批")
        
        self.status = "已审批"
        self.approved_by = frappe.session.user
        self.approved_date = get_datetime()
        self.save()
        
        # 发送通知
        self.send_approval_complete_notification()
        
        return True
    
    def reject(self, reason=""):
        """拒绝"""
        if self.status != "待审批":
            frappe.throw("只有待审批状态的清单才能拒绝")
        
        self.status = "草稿"
        self.save()
        
        # 发送通知
        self.send_rejection_notification(reason)
        
        return True
    
    def mark_as_issued(self):
        """标记为已领料"""
        if self.status != "已审批":
            frappe.throw("只有已审批状态的清单才能标记为已领料")
        
        self.status = "已领料"
        self.issued_by = frappe.session.user
        self.issued_date = get_datetime()
        self.save()
        
        # 更新子表项状态
        for item in self.materials:
            if item.status == "待领料":
                item_doc = frappe.get_doc("Batch Material List Item", item.name)
                item_doc.mark_as_issued()
        
        return True
    
    def mark_as_completed(self):
        """标记为已完成"""
        if self.status != "已领料":
            frappe.throw("只有已领料状态的清单才能标记为已完成")
        
        # 检查是否所有项都已领料
        for item in self.materials:
            if item.status != "已领料":
                frappe.throw("还有未领料的余料，无法标记为已完成")
        
        self.status = "已完成"
        self.completed_by = frappe.session.user
        self.completed_date = get_datetime()
        self.save()
        
        return True
    
    def reset_to_draft(self):
        """重置为草稿状态"""
        self.status = "草稿"
        self.approved_by = ""
        self.approved_date = ""
        self.issued_by = ""
        self.issued_date = ""
        self.completed_by = ""
        self.completed_date = ""
        self.save()
        
        # 重置子表项状态
        for item in self.materials:
            if item.status == "已领料":
                item_doc = frappe.get_doc("Batch Material List Item", item.name)
                item_doc.reset_to_pending()
        
        return True
    
    def send_approval_notification(self):
        """发送审批通知"""
        # 获取审批人
        approvers = frappe.db.get_all("Has Role", {
            "role": "Scrap Manager",
            "parenttype": "User"
        }, pluck="parent")
        
        # 发送通知
        for approver in approvers:
            frappe.sendmail(
                recipients=[approver],
                subject=f"批次领料清单 {self.material_list_id} 待审批",
                message=f"""
                <p>您好，</p>
                <p>批次领料清单 <strong>{self.material_list_id}</strong> 需要您的审批。</p>
                <p>清单详情：</p>
                <ul>
                    <li>领料日期：{self.material_date}</li>
                    <li>仓库：{self.warehouse}</li>
                    <li>优先级：{self.priority}</li>
                    <li>总数量：{self.total_quantity}</li>
                    <li>总金额：{self.total_amount}</li>
                </ul>
                <p>请登录系统进行审批。</p>
                <p>谢谢！</p>
                """,
                reference_doctype=self.doctype,
                reference_name=self.name
            )
    
    def send_approval_complete_notification(self):
        """发送审批完成通知"""
        # 发送通知给创建人
        frappe.sendmail(
            recipients=[self.created_by],
            subject=f"批次领料清单 {self.material_list_id} 审批完成",
            message=f"""
            <p>您好，</p>
            <p>您的批次领料清单 <strong>{self.material_list_id}</strong> 已通过审批。</p>
            <p>审批人：{self.approved_by}</p>
            <p>审批时间：{format_datetime(self.approved_date)}</p>
            <p>请登录系统进行后续操作。</p>
            <p>谢谢！</p>
            """,
            reference_doctype=self.doctype,
            reference_name=self.name
        )
    
    def send_rejection_notification(self, reason):
        """发送拒绝通知"""
        # 发送通知给创建人
        frappe.sendmail(
            recipients=[self.created_by],
            subject=f"批次领料清单 {self.material_list_id} 审批被拒绝",
            message=f"""
            <p>您好，</p>
            <p>您的批次领料清单 <strong>{self.material_list_id}</strong> 审批被拒绝。</p>
            <p>拒绝原因：{reason}</p>
            <p>请登录系统进行修改后重新提交。</p>
            <p>谢谢！</p>
            """,
            reference_doctype=self.doctype,
            reference_name=self.name
        )
    
    @frappe.whitelist()
    def get_material_list_list(self, status=None, warehouse=None, from_date=None, to_date=None):
        """获取领料清单列表"""
        filters = {}
        
        if status:
            filters["status"] = status
        if warehouse:
            filters["warehouse"] = warehouse
        if from_date:
            filters["material_date"] = [">=", from_date]
        if to_date:
            filters["material_date"] = ["<=", to_date]
        
        return frappe.db.get_all("Batch Material List",
            filters=filters,
            fields=["name", "material_list_id", "material_date", "warehouse", "priority", "status", "total_quantity", "total_amount"],
            order_by="material_date desc"
        )
    
    @frappe.whitelist()
    def get_pending_approval_lists(self):
        """获取待审批的清单"""
        return frappe.db.get_all("Batch Material List",
            filters={"status": "待审批"},
            fields=["name", "material_list_id", "material_date", "warehouse", "priority", "created_by", "created_date"],
            order_by="priority desc, material_date asc"
        )
    
    @frappe.whitelist()
    def get_approved_lists(self):
        """获取已审批的清单"""
        return frappe.db.get_all("Batch Material List",
            filters={"status": ["in", ["已审批", "已领料", "已完成"]]},
            fields=["name", "material_list_id", "material_date", "warehouse", "priority", "approved_by", "approved_date", "status"],
            order_by="approved_date desc"
        )